<?php


class Placeholder extends A_Content {
	
	/**
	 * 
	 * @see A_Content::add()
	 * @return SinglePlaceholder
	 */
	public function add() {
		$this->_top->_sql->exeDummy("INSERT INTO `".TAB_PREF."placeholder` (`add_date`) VALUES ( NOW() );");
		return $this->getById($this->_top->_sql->last_insert_id());
	}
	
	/**
	 * 
	 * @see A_Content::getById()
	 * @return SinglePlaceholder
	 */
	public function getById($id) {
		if (!isset($this->_cashe_obj[$id])) {
			$this->_cashe_obj[$id] = new SinglePlaceholder($this->_top,$this,$id);
		}
		return $this->_cashe_obj[$id]; 
	}
	
	/**
	 * Производит расцепку всего контента находящегося в плэйсхолдерах 
	 * и привязанного к указанному геопризнаку
	 *  
	 */
	public function unlinkContentFromGeo($geo) {
		$ph_list = $this->_top->_sql->exe("SELECT `placeholder_id` FROM `{$this->_top->_sql->tab_pref}placeholder`");
		for ($l=0;$l<count($ph_list);$l++) {
			$ph = $this->getById($ph_list[$l]['placeholder_id']);
			for ($i=0;$i<$ph->length();$i++) {
				$ph->item($i)->unlinkGeo($geo);
			}
		}
	}
	
}

class SinglePlaceholder extends A_SingleContent  {
	
	private $_placeholderContent = array();
	private $_avalible_types = array();
	private $_geo_filter_cashe = array();
	
	
	protected function loader() {
		$getData = $this->_top->_sql->exe("SELECT * FROM `".TAB_PREF."placeholder` 
			WHERE `placeholder_id`='{$this->_content_id}'");
		$this->_data = $getData[0];
		$this->_data['content'] = array();
		$get_content = $this->_top->_sql->exe("SELECT `placeholder2content_id` FROM `".TAB_PREF."placeholder2content` 
			WHERE `placeholder_id`='{$this->_content_id}' ORDER BY `sequence` ASC");
		for ($c=0;$c<count($get_content);$c++) {
			array_push($this->_data['content'],$get_content[$c]['placeholder2content_id']);
		}
		if (trim($this->_data['avalible_types'])!='') {
			$this->_avalible_types = explode(',',$this->_data['avalible_types']);
		}
		
		
		if (count($this->_geo_filter_cashe)>0) {
			$geo_ids = array_keys($this->_geo_filter_cashe);
			for ($i=0;$i<count($geo_ids);$g++) {
				$this->_geo_filter_cashe[$geo_ids[$g]]->__construct($this,$this->_top,$geo_ids[$g]);
			}
		}
	}

	public function applyXML($xml_obj) {
		if ($xml_obj==null) {
			return false;
		}
		
		for ($n=0;$n<count($xml_obj);$n++) {
			$this->addType($xml_obj[$n]->getAttribute('type'));
		}
	}
	
	
	public function __get($param) {
		if ($param=="avalible_types") {
			return $this->getTypes();
		} elseif ($param=="content") {
			return false;
		} elseif (isset($this->_data[$param])) {
			return $this->_data[$param];
		} else {
			return false;
		}
		
	}
	
	public function __set($param,$value) {
		return false;
	}
	
	/**
	 * @see A_SingleContent::deleter()
	 * @return void
	 */
	protected function deleter() {
		for ($i=0;$i<$this->length();$i++) {
			$this->item($i)->delete();
		}
		$this->_top->_sql->exeDummy("DELETE FROM `".TAB_PREF."placeholder` 
			WHERE `placeholder_id`='{$this->_content_id}'");
		unset($this->_placeholderContent);
		unset($this->_avalible_types);
	}

	
	public function length() {
		return count($this->_data['content']);
	}
	
	/**
	 * Returns pointer to Placeholder to Content link object
	 *
	 * @param Ineger $idx
	 * @return SinglePlaceholderContent
	 */
	public function item($idx) {
		return $this->getById($this->_data['content'][$idx]);
	}
	
	/**
	 * Returns pointer to Placeholder to Content link object
	 *
	 * @param Ineger $id
	 * @return SinglePlaceholderContent
	 */
	public function getById($id) {
		if (!isset($this->_placeholderContent[$id])) {
			$this->_placeholderContent[$id] = new SinglePlaceholderContent($this->_top,$this,$id);
		}
		return $this->_placeholderContent[$id];
	}
	
	
	public function addType($type_name) {
		if ($this->checkType($type_name)) {
			$this->_top->Utils->PushError("The content type if already in list of avalible types","Добавляемый тип уже в списке разрешенных");
		}
		array_push($this->_avalible_types,$type_name);
		$this->saveTypes();
	}
	
	public function deleteType($type_name) {
		$type_key = array_search($type_name,$this->_avalible_types);
		if (!$type_key) {
			$this->_top->Utils->PushError("Trying to delete unexsisting content type","Данного типа нет в списке разрешенных");
		}
		array_splice($this->_avalible_types,$type_key,1);
		$this->saveTypes();
	}
	
	/**
	 * Доступные для добавления типы контента
	 *
	 * @var array
	 */
	public function getTypes() {
		return $this->_avalible_types;
	}
	
	public function checkType($type_name) {
		return in_array(strtolower($type_name),$this->_avalible_types);
	}
	
	private function saveTypes() {
		$this->_top->_sql->exeDummy("UPDATE `".TAB_PREF."placeholder` 
			SET `avalible_types`='".implode(",",$this->_avalible_types)."'
			WHERE `placeholder_id`='{$this->_content_id}'");
	}
	
	public function rebuildContentSequence($id = null,$place = null) {
		
		if (($place<1 || $place>$this->length()) && $place!==null) {
			return false;
		}
		
		
		if ($id!=null && $place != null) {
			$this->_top->_sql->exeDummy("UPDATE `".TAB_PREF."placeholder2content`
				SET `sequence`='$place' WHERE `placeholder2content_id`='{$id}'");
		}
		
		$sequence = 1;
		for ($i=0;$i<$this->length();$i++) {
			if ($this->item($i)->_content_id!=$id) {
				if ($sequence==$place && $id!=null) {
					$sequence++;
				}
				
				if (isset($this->item($i)->_content_id) && $this->item($i)->_content_id!=$id) {
					$this->_top->_sql->exeDummy("UPDATE `".TAB_PREF."placeholder2content`
						SET `sequence`='$sequence' WHERE `placeholder2content_id`='{$this->item($i)->_content_id}'");
					$sequence++;
				}
			}
		}
		
		$this->loader();
		
	}

	/**
	 * Adds and then Returns pointer to Placeholder to Content link object
	 *
	 * @param String $content_type
	 * @return SinglePlaceholderContent
	 */
	public function add($content_type) {
		$find_max_sequence = $this->_top->_sql->exe("SELECT IFNULL(MAX(`sequence`),1)+1 as s FROM `".TAB_PREF."placeholder2content` 
			WHERE `placeholder_id`='{$this->_content_id}' lIMIT 1");
		$max_sequence = $find_max_sequence[0]['s'];
		
		$new_content_id = $this->_top->Content($content_type)->add()->_content_id;
		$content_type = $this->_top->Utils->prepareValueForSQL($content_type);
		$this->_top->_sql->exeDummy("INSERT INTO `".TAB_PREF."placeholder2content` (`placeholder_id`, `content_id`, `content_type`, `sequence`)
			VALUES ({$this->_content_id},$new_content_id,'$content_type',$max_sequence)");
		$placeholderContentId = $this->_top->_sql->last_insert_id();
		$this->loader();
		return $this->getById($placeholderContentId);
	}
	
	/**
	 * Возвращает список элементов контента отфилтрованных по заданному гео-признаку
	 *
	 * @param SingleGeo|Integer $geo
	 * @return SinglePlaceholderGeo
	 */
	public function applyGeoFilter($geo) {
		if (is_object($geo)) {
			if (get_class($geo)!=='SingleGeo') {
				throw $this->_top->Utils->PushError('Undefined varible type putted in method','Системная ошибка. Обраитесь к администратору');
			}
		} else {
			$geo = $this->_top->Geo->getById($geo);
		}
		
		if (!isset($this->_geo_filter_cashe[$geo->_content_id])) {
			$this->_geo_filter_cashe[$geo->_content_id] = new SinglePlaceholderGeo($this,$this->_top,$geo);
		}
		return $this->_geo_filter_cashe[$geo->_content_id];
	}
	
}

class SinglePlaceholderGeo   {
	
	/**
	 * Enter description here...
	 *
	 * @var MF_Main
	 */
	private $_top;
	/**
	 * Enter description here...
	 *
	 * @var SinglePlaceholder
	 */
	private $_ph;
	
	private $_cashe_obj = array();
	
	/**
	 * Enter description here...
	 *
	 * @param SinglePlaceholder $ph
	 * @param MF_Main $top
	 * @param SingleGeo|Integer $geo
	 */
	function __construct($ph,$top,$geo) {
		if (is_object($geo)) {
			if (get_class($geo)!=='SingleGeo') {
				throw $this->_top->Utils->PushError('Undefined varible type putted in method','Системная ошибка. Обраитесь к администратору');
			}
		} else {
			$geo = $this->_top->Geo->getById($geo);
		}
		
		$this->_ph = $ph;
		
		$getPhList = $top->_sql->exe("SELECT c.`placeholder2content_id`
			FROM `{$top->_sql->tab_pref}placeholder2content` c, 
				`{$top->_sql->tab_pref}placeholder2content2geo` g
			WHERE c.`placeholder_id` ='{$this->_ph->_content_id}'
			AND g.`placeholder2content_id` = c.`placeholder2content_id`
			AND g.geo_id ='{$geo->_content_id}' ORDER BY `sequence` ASC");
		for ($l=0;$l<count($getPhList);$l++) {
			array_push($this->_cashe_obj,$getPhList[$l]['placeholder2content_id']);
		}
	}
	
	public function length() {
		return count($this->_cashe_obj);
	}
	
	/**
	 * Returns pointer to Placeholder to Content link object
	 *
	 * @param Ineger $idx
	 * @return SinglePlaceholderContent
	 */
	public function item($idx) {
		return $this->_ph->getById($this->_cashe_obj[$idx]);
	}
}


class SinglePlaceholderContent extends A_SingleContent   {
	
	
	/**
	 * @see A_SingleContent::loader()
	 *
	 */
	protected function loader() {
		$getData = $this->_top->_sql->exe("SELECT * FROM `".TAB_PREF."placeholder2content` 
			WHERE `placeholder2content_id`='{$this->_content_id}'");
		$this->_data = $getData[0];
		$this->_data['data'] = $this->_top->Content($this->_data['content_type'])->getById($this->_data['content_id']);
	}
	
	public function __get($param) {
		if ($param=="sequence") {
			$get_sequence = $this->_top->_sql->exe("SELECT `sequence` FROM `".TAB_PREF."placeholder2content` 
				WHERE `placeholder2content_id`='{$this->_content_id}'");
			return $get_sequence[0]['sequence'];
		} elseif (isset($this->_data[$param])) {
			return $this->_data[$param];
		} else {
			return false;
		}
	}
	
	public function __set($param,$value) {
		if ($param=="sequence") {
			$this->_parent->rebuildContentSequence($this->_content_id,$value);
		} elseif ($param=="name") {
			$this->_data[$param] = $value;
			$value = $this->_top->Utils->prepareValueForSQL($value);
			$this->_top->_sql->exeDummy("UPDATE `".TAB_PREF."placeholder2content` 
				SET `name`='$value' WHERE `placeholder2content_id`='{$this->_content_id}'");
		} else {
			return false;
		}
		
	}
	
	
	/**
	 * @see A_SingleContent::deleter()
	 *
	 */
	protected function deleter() {
		$this->data->delete();
		$this->_top->_sql->exeDummy("DELETE FROM `".TAB_PREF."placeholder2content` 
			WHERE `placeholder2content_id`='{$this->_content_id}'");
		$this->_parent->rebuildContentSequence($this->_content_id);
	}
	
	
	private function getSingleGeo(&$geo) {
		if (is_object($geo)) {
			if (get_class($geo)!=='SingleGeo') {
				throw $this->_top->Utils->PushError('Undefined varible type putted in method','Системная ошибка. Обраитесь к администратору');
			}
		} else {
			$geo = $this->_top->Geo->getById($geo);
		}
	}
	
	
	/**
	 * Привязывает контент из плейсхолдера к географическому признаку
	 *
	 * @param SingleGeo|Integer $geo
	 */
	public function linkGeo($geo) {
		$this->getSingleGeo($geo);
		
		$this->_top->_sql->exeDummy("INSERT INTO `{$this->_top->_sql->tab_pref}placeholder2content2geo` ( `placeholder2content_id` , `geo_id` )
			VALUES ('{$this->_content_id}', '{$geo->_content_id}');");
		
	}
	
	/**
	 * Привязывает контент из плейсхолдера к географическому признаку
	 *
	 * @param SingleGeo|Integer $geo
	 */
	public function unlinkGeo($geo) {
		$this->getSingleGeo($geo);
		
		$this->_top->_sql->exeDummy("DELETE FROM `{$this->_top->_sql->tab_pref}placeholder2content2geo`
			WHERE `placeholder2content_id`='{$this->_content_id}' AND `geo_id`='{$geo->_content_id}'");
	}
	
	public function checkGeo($geo) {
		$this->getSingleGeo($geo);
		$find_link = $this->_top->_sql->exe("SELECT * FROM `{$this->_top->_sql->tab_pref}placeholder2content2geo`
			WHERE `placeholder2content_id`='{$this->_content_id}' AND `geo_id`='{$geo->_content_id}'");
		return count($find_link)==0 ? false : true;
	}
	
}

?>